package com.eascs.spider.ant.worker.spider;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import com.alibaba.fastjson.JSON;
import com.eascs.spider.ant.common.proj.Platform;
import com.eascs.spider.ant.common.proj.Task;
import com.eascs.spider.ant.common.util.CommonUtil;
import com.eascs.spider.ant.common.util.NetUtil;
import com.eascs.spider.ant.common.util.StringUtil;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

public class CarAutoHomeSpider extends SimpleSpider{
	
	private Map<String, Object> data = new HashMap<String, Object>();
	
	public CarAutoHomeSpider(String url) {
		super(url);
	}
	

	@Override
	public void run() {
		Map<String, String> header = new HashMap<String, String>();
		header.put("Referer", "https://dealer.autohome.com.cn");
		header.put("Host", "dealer.autohome.com.cn");
		
		if(url.equals("https://dealer.autohome.com.cn")) {
			//入口是主页
			//如果访问主页，进行地级市链接的构造
			logger.info("汽车之家经销商主页");
			String ajaxUrl = "https://dealer.autohome.com.cn/Ajax?actionName=GetAreasAjax";
			Map<String, Object> map = extractJson(ajaxUrl);
			String temp = JSON.toJSONString(map);
			Matcher ma = Pattern.compile("\"Pinyin\":\"([a-z]+)\",\"Count\":\\d+\\.0}").matcher(temp);
			while(ma.find()) {
				String areaUrl = "https://dealer.autohome.com.cn/"+ma.group(1);
				Task task = new Task();
				task.setUrl(areaUrl)
					.setMethod(Task.HTTP_GET)
					.setHomepage(Task.HOMEPAGE_NO)
					.setHeaderMap(header);
				manager.addSendQueue(task);
			}
			return ;
		} else {
			String html = NetUtil.loadPageRawTextByGet(url, client, header, null, "utf-8");
			if(StringUtil.isNullOrEmpty(html)) {
				logger.warn("html为空,url:{}" ,url);
				reAddTask(url);
				CommonUtil.sleep(2000);
				return ;
			}
			String judgeUrl = url.replace("https://dealer.autohome.com.cn/", "");
			if(judgeUrl.indexOf("/") != -1) {
				judgeUrl = judgeUrl.substring(0, judgeUrl.indexOf("/"));
			}
			Pattern pattern1 = Pattern.compile("//dealer.autohome.com.cn/.*?/#pvareaid=2113601");
			Pattern pattern2 = Pattern.compile("[a-z]+");
			if(StringUtil.isNullOrEmpty(html)) {
				logger.warn("html为空,url:{}" ,url);
				String refererUrl;
				if(pattern1.matcher(url).find() || pattern2.matcher(judgeUrl).find()) {
					refererUrl = "https://dealer.autohome.com.cn";
				} else {
					refererUrl = url.substring(0, url.indexOf("spec"))+"price.html";
				}
				reAddTask(refererUrl);
				CommonUtil.sleep(2000);
				return ;
			}
			if(pattern1.matcher(url).find()) {
				String refererUrl;
				if(pattern1.matcher(url).find() || pattern2.matcher(judgeUrl).find()) {
					refererUrl = "https://dealer.autohome.com.cn";
				} else {
					refererUrl = url.substring(0, url.indexOf("spec"))+"price.html";
				}
				//reAddTask(refererUrl);
			} else if(pattern1.matcher(url).find()) {
				//如果是经销商页面，爬取汽车详情url  
				logger.debug("经销商页面,url:{}" ,url);
				extractCarUrl();
			} else if(pattern2.matcher(judgeUrl).find()) {
				//如果是地区首页,爬取分页url及经销商url
				logger.debug("地区首页,url:{}" ,url);
				extractPageUrl(html);
			} else {
				//如果不属于以上情况，爬取汽车报价及详情
				logger.debug("汽车详情页面,url:{}" ,url);
				extractInfo(html);
			} 
			CommonUtil.sleep(2000);
		}
	}
	
	public void extractPageUrl(String html) {
		Document document = Jsoup.parse(html);
		String dealerNum = document.select("span.num.data-dealer-count").text();
		Integer num = Integer.valueOf(dealerNum);
		try {
			int pageSize = num%15 == 0 ? num/15 : num/15 + 1;
			Map<String, String> header = new HashMap<String, String>();
			header.put("Referer", url);
			header.put("Host", "dealer.autohome.com.cn");
			for(int i = 1;i <= pageSize;i ++) {
				Map<String, String> param = new HashMap<String, String>();
				param.put("pageIndex", i+"");
				String htmlInfo = NetUtil.loadPageRawTextByGet(url, client, header, param, "utf-8");
				extractDealerUrl(htmlInfo, header);
				CommonUtil.sleep(2000);
			}
		} catch (NumberFormatException e) {
			logger.info("异常商家数量{}" ,dealerNum);
			reAddTask(url);
		} 
	}
	
	public void extractDealerUrl(String html, Map<String, String> header) {
		Pattern pattern = Pattern.compile("//dealer.autohome.com.cn/.*?/#pvareaid=2113601");
		Matcher matcher = pattern.matcher(html);
		while(matcher.find()) {
			Task task = new Task();
			task.setUrl("https:"+matcher.group())
				.setMethod(Task.HTTP_GET)
				.setHomepage(Task.HOMEPAGE_NO)
				.setHeaderMap(header);
			manager.addSendQueue(task);
		}
	}
	
	public void extractCarUrl() {
		Map<String, String> header = new HashMap<String, String>();
		header.put("Referer", url);
		header.put("Host", "dealer.autohome.com.cn");
		String carsUrl = url.substring(0, url.indexOf("#pvareaid")) + "price.html";
		String html = NetUtil.loadPageRawTextByGet(carsUrl, client, header, null, "utf-8");
		if(StringUtil.isNullOrEmpty(html)) {
			logger.info("经销商车型报价页面出错，html为空，url：{}",carsUrl);
			reAddTask(carsUrl);
			return ;
		}
		Document document = Jsoup.parse(html);
		Elements elements = document.select("td.txt-left a");
		Iterator<Element> iterator = elements.iterator();
		while(iterator.hasNext()) {
			Element element = iterator.next();
			if(!element.select("i").attr("class").equals("icon16 icon16-ding")) {
				String carUrl = "https://dealer.autohome.com.cn"+element.attr("href");
				Task task = new Task();
				task.setUrl(carUrl)
					.setMethod(Task.HTTP_GET)
					.setHomepage(Task.HOMEPAGE_NO)
					.setHeaderMap(header);
				manager.addSendQueue(task);
			}
		}
	}
	
	public void extractInfo(String html) {
		try {
			Date date = new Date();
			Map<String, Object> map = new HashMap<String,Object>();
			Document document = Jsoup.parse(html);
			String title = document.select("p.topname-text").text();  //标题
			String bareCar = document.select("span.text-line.fn-fontsize12-b").text();   //裸车价
			String price = document.select("span.price").text();   //限时促销
			String phone = document.select("span.dealer-api-phone").text().split(" ")[0];   //咨询电话	
			String storeName = document.select("div.text-main").text();
			
			String specId = document.select("input#specId").val();
			map = extractJson("https://dealer.autohome.com.cn/Ajax/GetPraise?specId="+specId);
			if(map != null) {
				Map<String, Object> result = (Map<String, Object>)map.get("result");
				if(result != null) {
					ArrayList<Map<String, Object>> individualRank = (ArrayList<Map<String, Object>>)result.get("individualRank");
					Iterator<Map<String, Object>> iterator = individualRank.iterator();
					int count = 0;
					float average = 0;
					while(iterator.hasNext()) {
						count ++;
						Map<String, Object> m = iterator.next();
						String aver = m.get("average").toString();
						average = average + Float.valueOf(aver).floatValue();
					}
					average /= count;
					DecimalFormat decimalFormat=new DecimalFormat(".00");
					String aver=decimalFormat.format(average);    //口碑评分
					data.put("口碑评分", aver);
				} else {
					data.put("口碑评分", 0);
				}
			} else {
				logger.info("Ajax请求失败，无法获取数据，url：{}",url);
				reAddTask(url.substring(0, url.indexOf("spec"))+"price.html");
				return ;
			}
			
			String storeUrl = url.substring(0, url.indexOf("/spec"));

			
			//参考总价及详情
			String ajaxUrl = "https://dealer.autohome.com.cn" + html.substring(html.indexOf("/Ajax/GetPriceDetail?"), html.indexOf("&DealerSpecInfoShowPrice="));
			map = extractJson(ajaxUrl);
			if(map != null) {
				String detail = (String)map.get("detail");
				String[] details = null;
				boolean spec = (boolean)map.get("hasSpecPriceDetail");
				if(spec) {
					details = detail.split("\\|");
					data.put("购置税", details[1]+"元");
					data.put("车船税", details[2]+"元");
					data.put("商业险", details[3]+"元");
					data.put("交强险价", details[4]+"元");
					data.put("保险优惠", details[5]+"元");
					data.put("上牌费用", details[6]+"元");
					data.put("其他", details[7]+"元");
					data.put("参考总价", details[8]+"元");
				} else {
					data.put("购置税", "无");
					data.put("车船税", "无");
					data.put("商业险", "无");
					data.put("交强险价", "无");
					data.put("保险优惠", "无");
					data.put("上牌费用", "无");
					data.put("其他", "无");
					data.put("参考总价", "无");
				}
			} else {
				logger.info("Ajax请求失败，无法获取数据，url：{}",url);
				reAddTask(url.substring(0, url.indexOf("spec"))+"price.html");
				return ;
			}
			
			data.put("裸车价", bareCar);
			data.put("限时促销", price);
			data.put("标题", title);
			data.put("咨询电话", phone);
			data.put("url", url);
			data.put("店铺名", storeName);
			data.put("店铺url", storeUrl);
			data.put("店铺地址", extraAddress(storeUrl));
			data.put("crawler_time", date);
			
			//爬取车型介绍以及配置信息
			ajaxUrl = html.substring(html.indexOf("/Price/_SpecConfig?"), html.length()-1);
			ajaxUrl = "https://dealer.autohome.com.cn" + ajaxUrl.substring(0, ajaxUrl.indexOf("\""));
			extralMore(ajaxUrl);
			logger.info("单条数据,url:{}" ,url);
			mongoSession.setData(data, Platform.CAR_AUTOHOME);
		} catch (IndexOutOfBoundsException e) {
			logger.error("下标越界,html:{}" ,html ,e);
		}
	}
	
	
	
	public Map<String,Object> extractJson(String url) {
		Map<String, String> header = new HashMap<String, String>();
		header.put("Referer", this.url);
		header.put("Host", "dealer.autohome.com.cn");
		String html = NetUtil.loadPageRawTextByGet(url, client, header, null, "utf-8");
		if(StringUtil.isNullOrEmpty(html)) {
			logger.info("Ajax请求访问失败，无法获取数据，url：{}",this.url);
			reAddTask(this.url);
		}
		Map<String,Object> map = new Gson().fromJson(html, new TypeToken<HashMap<String,Object>>(){}.getType()); 
		CommonUtil.sleep(2000);
		return map;
	}
	
	
	public String extraAddress(String url) {
		Map<String, String> header = new HashMap<String, String>();
		header.put("Referer", this.url);
		header.put("Host", "dealer.autohome.com.cn");
		String html = NetUtil.loadPageRawTextByGet(url, client, header, null, "utf-8");
		Document document = Jsoup.parse(html);
		CommonUtil.sleep(2000);
		return document.select("p.address").attr("title");
	}
	
	
	public void extralMore(String url) {
		Map<String, String> header = new HashMap<String, String>();
		header.put("Referer", this.url);
		header.put("Host", "dealer.autohome.com.cn");
		String html = NetUtil.loadPageRawTextByGet(url, client, header, null, "utf-8");
		Document document = Jsoup.parse(html);    
		Document modelDoc = Jsoup.parse(document.select("div#tab-10").toString());   //车型介绍
		Document confDoc = Jsoup.parse(document.select("div#tab-11").toString());   //配置信息
		
		Elements modelThs = modelDoc.getElementsByTag("th");
		Elements modelTds = modelDoc.getElementsByTag("td");
		Elements confThs = confDoc.getElementsByTag("th");
		Elements confTds = confDoc.getElementsByTag("td");
		
		Iterator<Element> mThs = modelThs.iterator();
		Iterator<Element> mTds = modelTds.iterator();
		Iterator<Element> cThs = confThs.iterator();
		Iterator<Element> cTds = confTds.iterator();
		
		Map<String, Object> model = new HashMap<String, Object>();
		while(mThs.hasNext() && mTds.hasNext()) {
			String strTh = mThs.next().text().trim();
			String strTd = mTds.next().text().trim();
			if(strTh.equals("-") || strTd.equals("-")) {
				continue;
			}
			model.put(strTh, strTd);
		}
		
		Map<String, Object> config = new HashMap<String, Object>();
		while(cThs.hasNext() && cTds.hasNext()) {
			String strTh = cThs.next().text().trim();
			String strTd = cTds.next().text().trim();
			if(strTh.equals("-") || strTd.equals("-")) {
				continue;
			}
			config.put(strTh, strTd);
		}
		data.put("车型介绍", JSON.toJSONString(model));
		data.put("配置信息", JSON.toJSONString(config));
	}
	
	
	public void reAddTask(String url) {
		Map<String, String> header = new HashMap<String, String>();
		header.put("Referer", url.substring(0, url.indexOf("/spec_"))+"/price.html");
		header.put("Host", "dealer.autohome.com.cn");
		Task task = new Task();
		task.setUrl(this.url)
			.setMethod(Task.HTTP_GET)
			.setHomepage(Task.HOMEPAGE_NO)
			.setHeaderMap(header);
		manager.addSendQueue(task);
	}
	
	
	public static void main(String[] args) {
		Thread thread = new Thread(new CarAutoHomeSpider("https://dealer.autohome.com.cn/126212/spec_14509.html?siteID=4&pvareaid=100928"));
		thread.start();
	}
}
